using Engine;
using Engine.Graphics;
using Game;

namespace RuthlessConquest {
    public class BevelledRectangleWidget : Widget {
        public FlatBatch2D m_flatBatch;

        public TexturedBatch2D m_texturedBatch;

        public Texture2D m_texture;

        public bool m_textureLinearFilter;

        public Vector2 Size { get; set; }

        public float BevelSize { get; set; }

        public float DirectionalLight { get; set; }

        public float AmbientLight { get; set; }

        public Texture2D Texture {
            get => m_texture;
            set {
                if (value != m_texture) {
                    m_texture = value;
                    m_texturedBatch = null;
                }
            }
        }

        public float TextureScale { get; set; }

        public bool TextureLinearFilter {
            get => m_textureLinearFilter;
            set {
                if (value != m_textureLinearFilter) {
                    m_textureLinearFilter = value;
                    m_texturedBatch = null;
                }
            }
        }

        public Color CenterColor { get; set; }

        public Color BevelColor { get; set; }

        public Color ShadowColor { get; set; }

        public BevelledRectangleWidget() {
            Size = new Vector2(float.PositiveInfinity);
            BevelSize = 2f;
            AmbientLight = 0.6f;
            DirectionalLight = 0.4f;
            TextureScale = 1f;
            TextureLinearFilter = false;
            CenterColor = Colors.Panel;
            BevelColor = Colors.Panel;
            ShadowColor = new Color(0, 0, 0, 80);
            IsHitTestVisible = false;
        }

        public override void Draw(DrawContext dc) {
            if (Texture != null) {
                m_texturedBatch ??= dc.PrimitivesRenderer2D.TexturedBatch(
                    Texture,
                    false,
                    0,
                    DepthStencilState.None,
                    null,
                    null,
                    TextureLinearFilter ? SamplerState.LinearWrap : SamplerState.PointWrap
                );
                m_flatBatch ??= dc.PrimitivesRenderer2D.FlatBatch(0, DepthStencilState.None);
                int count = m_flatBatch.TriangleVertices.Count;
                int count2 = m_texturedBatch.TriangleVertices.Count;
                QueueBevelledRectangle(
                    m_texturedBatch,
                    m_flatBatch,
                    Vector2.Zero,
                    ActualSize,
                    0f,
                    BevelSize,
                    CenterColor * GlobalColorTransform,
                    BevelColor * GlobalColorTransform,
                    ShadowColor * GlobalColorTransform,
                    AmbientLight,
                    DirectionalLight,
                    TextureScale
                );
                m_flatBatch.TransformTriangles(GlobalTransform, count);
                m_texturedBatch.TransformTriangles(GlobalTransform, count2);
            }
            else {
                m_flatBatch ??= dc.PrimitivesRenderer2D.FlatBatch(0, DepthStencilState.None);
                int count3 = m_flatBatch.TriangleVertices.Count;
                QueueBevelledRectangle(
                    null,
                    m_flatBatch,
                    Vector2.Zero,
                    ActualSize,
                    0f,
                    BevelSize,
                    CenterColor * GlobalColorTransform,
                    BevelColor * GlobalColorTransform,
                    ShadowColor * GlobalColorTransform,
                    AmbientLight,
                    DirectionalLight,
                    0f
                );
                m_flatBatch.TransformTriangles(GlobalTransform, count3);
            }
        }

        public override void MeasureOverride(Vector2 parentAvailableSize) {
            IsDrawRequired = BevelColor.A != 0 || CenterColor.A != 0;
            DesiredSize = Size;
        }

        public static void QueueBevelledRectangle(TexturedBatch2D texturedBatch,
            FlatBatch2D flatBatch,
            Vector2 c1,
            Vector2 c2,
            float depth,
            float bevelSize,
            Color color,
            Color bevelColor,
            Color shadowColor,
            float ambientLight,
            float directionalLight,
            float textureScale) {
            float num = MathUtils.Abs(bevelSize);
            Vector2 vector = c1;
            Vector2 vector2 = c1 + new Vector2(num);
            Vector2 vector3 = c2 - new Vector2(num);
            Vector2 vector4 = c2;
            Vector2 vector5 = c2 + new Vector2(1.5f * num);
            float x = vector.X;
            float x2 = vector2.X;
            float x3 = vector3.X;
            float x4 = vector4.X;
            float x5 = vector5.X;
            float y = vector.Y;
            float y2 = vector2.Y;
            float y3 = vector3.Y;
            float y4 = vector4.Y;
            float y5 = vector5.Y;
            float num2 = MathUtils.Saturate((bevelSize > 0f ? 1f : -0.75f) * directionalLight + ambientLight);
            float num3 = MathUtils.Saturate((bevelSize > 0f ? -0.75f : 1f) * directionalLight + ambientLight);
            float num4 = MathUtils.Saturate((bevelSize > 0f ? -0.375f : 0.5f) * directionalLight + ambientLight);
            float num5 = MathUtils.Saturate((bevelSize > 0f ? 0.5f : -0.375f) * directionalLight + ambientLight);
            float num6 = MathUtils.Saturate(0f * directionalLight + ambientLight);
            Color color2 = new((byte)(num4 * bevelColor.R), (byte)(num4 * bevelColor.G), (byte)(num4 * bevelColor.B), bevelColor.A);
            Color color3 = new((byte)(num5 * bevelColor.R), (byte)(num5 * bevelColor.G), (byte)(num5 * bevelColor.B), bevelColor.A);
            Color color4 = new((byte)(num2 * bevelColor.R), (byte)(num2 * bevelColor.G), (byte)(num2 * bevelColor.B), bevelColor.A);
            Color color5 = new((byte)(num3 * bevelColor.R), (byte)(num3 * bevelColor.G), (byte)(num3 * bevelColor.B), bevelColor.A);
            Color color6 = new((byte)(num6 * color.R), (byte)(num6 * color.G), (byte)(num6 * color.B), color.A);
            if (texturedBatch != null) {
                float num7 = textureScale / texturedBatch.Texture.Width;
                float num8 = textureScale / texturedBatch.Texture.Height;
                float num9 = x * num7;
                float num10 = y * num8;
                float x6 = num9;
                float x7 = (x2 - x) * num7 + num9;
                float x8 = (x3 - x) * num7 + num9;
                float x9 = (x4 - x) * num7 + num9;
                float y6 = num10;
                float y7 = (y2 - y) * num8 + num10;
                float y8 = (y3 - y) * num8 + num10;
                float y9 = (y4 - y) * num8 + num10;
                if (bevelColor.A > 0) {
                    texturedBatch.QueueQuad(
                        new Vector2(x, y),
                        new Vector2(x2, y2),
                        new Vector2(x3, y2),
                        new Vector2(x4, y),
                        depth,
                        new Vector2(x6, y6),
                        new Vector2(x7, y7),
                        new Vector2(x8, y7),
                        new Vector2(x9, y6),
                        color4
                    );
                    texturedBatch.QueueQuad(
                        new Vector2(x3, y2),
                        new Vector2(x3, y3),
                        new Vector2(x4, y4),
                        new Vector2(x4, y),
                        depth,
                        new Vector2(x8, y7),
                        new Vector2(x8, y8),
                        new Vector2(x9, y9),
                        new Vector2(x9, y6),
                        color3
                    );
                    texturedBatch.QueueQuad(
                        new Vector2(x, y4),
                        new Vector2(x4, y4),
                        new Vector2(x3, y3),
                        new Vector2(x2, y3),
                        depth,
                        new Vector2(x6, y9),
                        new Vector2(x9, y9),
                        new Vector2(x8, y8),
                        new Vector2(x7, y8),
                        color5
                    );
                    texturedBatch.QueueQuad(
                        new Vector2(x, y),
                        new Vector2(x, y4),
                        new Vector2(x2, y3),
                        new Vector2(x2, y2),
                        depth,
                        new Vector2(x6, y6),
                        new Vector2(x6, y9),
                        new Vector2(x7, y8),
                        new Vector2(x7, y7),
                        color2
                    );
                }
                if (color6.A > 0) {
                    texturedBatch.QueueQuad(new Vector2(x2, y2), new Vector2(x3, y3), depth, new Vector2(x7, y7), new Vector2(x8, y8), color6);
                }
            }
            else if (flatBatch != null) {
                if (bevelColor.A > 0) {
                    flatBatch.QueueQuad(new Vector2(x, y), new Vector2(x2, y2), new Vector2(x3, y2), new Vector2(x4, y), depth, color4);
                    flatBatch.QueueQuad(new Vector2(x3, y2), new Vector2(x3, y3), new Vector2(x4, y4), new Vector2(x4, y), depth, color3);
                    flatBatch.QueueQuad(new Vector2(x, y4), new Vector2(x4, y4), new Vector2(x3, y3), new Vector2(x2, y3), depth, color5);
                    flatBatch.QueueQuad(new Vector2(x, y), new Vector2(x, y4), new Vector2(x2, y3), new Vector2(x2, y2), depth, color2);
                }
                if (color6.A > 0) {
                    flatBatch.QueueQuad(new Vector2(x2, y2), new Vector2(x3, y3), depth, color6);
                }
            }
            if (bevelSize > 0f
                && flatBatch != null
                && shadowColor.A > 0) {
                Color color7 = shadowColor;
                Color color8 = new(0, 0, 0, 0);
                flatBatch.QueueTriangle(
                    new Vector2(x, y4),
                    new Vector2(x2, y5),
                    new Vector2(x2, y4),
                    depth,
                    color8,
                    color8,
                    color7
                );
                flatBatch.QueueTriangle(
                    new Vector2(x4, y),
                    new Vector2(x4, y2),
                    new Vector2(x5, y2),
                    depth,
                    color8,
                    color7,
                    color8
                );
                flatBatch.QueueTriangle(
                    new Vector2(x4, y4),
                    new Vector2(x4, y5),
                    new Vector2(x5, y4),
                    depth,
                    color7,
                    color8,
                    color8
                );
                flatBatch.QueueQuad(
                    new Vector2(x2, y4),
                    new Vector2(x2, y5),
                    new Vector2(x4, y5),
                    new Vector2(x4, y4),
                    depth,
                    color7,
                    color8,
                    color8,
                    color7
                );
                flatBatch.QueueQuad(
                    new Vector2(x4, y2),
                    new Vector2(x4, y4),
                    new Vector2(x5, y4),
                    new Vector2(x5, y2),
                    depth,
                    color7,
                    color7,
                    color8,
                    color8
                );
            }
        }
    }
}